#pragma once
#include <memory>
#include <mutex>
#include <atomic>
#include <QDebug>

//单例模式的ModRun（Singleton）;
template<class T>
class Singleton11T
{
protected:
    //私有化构造;
    Singleton11T() { qDebug() << "C++11T 单例构造"; };
    virtual ~Singleton11T() { qDebug() << "C++11T 单例析构"; };

private:

    //禁用拷贝构造和赋值重载
    Singleton11T(const Singleton11T& hs) = delete;
    Singleton11T& operator=(const Singleton11T& hs) = delete;
public:
    

    //获取实例;
    static T* GetInstance()
    {
        //获取内存中存储的值;
        T* temp = m_ptInstance.load(std::memory_order_relaxed);
        //获取内存栅栏;
        std::atomic_thread_fence(std::memory_order_acquire);
        if (nullptr == temp)
        {
            std::lock_guard<std::mutex> lock(m_tMtx);
            //获取内存中存储的值;
            temp = m_ptInstance.load(std::memory_order_relaxed);
            if (nullptr == temp)
            {
                temp = new T();
                //释放内存栅格;
                std::atomic_thread_fence(std::memory_order_release);
                m_ptInstance.store(temp, std::memory_order_relaxed);
            }
        }

        return temp;
    };

    //释放实例;
    static void Destory()
    {
        //获取内存中存储的值;
        T* temp = m_ptInstance.load(std::memory_order_relaxed);
        //获取内存栅栏;
        std::atomic_thread_fence(std::memory_order_acquire);
        if (nullptr != temp)
        {
            std::lock_guard<std::mutex> lock(m_tMtx);
            //获取内存中存储的值;
            temp = m_ptInstance.load(std::memory_order_relaxed);
            if (nullptr != temp)
            {
                delete temp;
                temp = nullptr;
                //释放内存栅格;
                std::atomic_thread_fence(std::memory_order_release);
                m_ptInstance.store(temp, std::memory_order_relaxed);
            }
        }
    };

private:
    //声明成员变量;
    static std::mutex m_tMtx;
    static std::atomic<T *> m_ptInstance;
};

//初始化成员变量;
template<class T>
std::mutex Singleton11T<T>::m_tMtx;

template<class T>
std::atomic<T*> Singleton11T<T>::m_ptInstance(nullptr);

